package com.kaisu.blog.web.file.controller;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import com.kaisu.blog.application.file.dto.FileDTO;
import com.kaisu.blog.application.file.service.FileService;
import com.kaisu.blog.common.exceptions.InternalException;
import com.kaisu.blog.common.util.FileUtils;
import com.kaisu.blog.domain.file.File;
import com.kaisu.blog.web.file.vo.FileUploadVO;
import com.kaisu.blog.web.result.Result;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author kaisu
 */
@Tag(name = "file", description = "文件")
@Slf4j
@RestController
@RequestMapping("/api/v1/file")
@RequiredArgsConstructor
public class FileController {
    private final FileService fileService;


    @PostMapping("upload")
    public Result<FileUploadVO> fileUpload(@RequestParam("file") MultipartFile multipartFile) {
        try {
            FileDTO file = fileService.uploadFile(multipartFile.getInputStream(), multipartFile.getOriginalFilename());
            return Result.success(new FileUploadVO(file.getId(), file.getPreviewPath()));
        } catch (IOException e) {
            throw new InternalException("文件上传失败！");
        }
    }

    @GetMapping(value = "image/preview/{id}")
    public void filePreview(HttpServletResponse response, @PathVariable String id) {
        FileDTO file = fileService.findById(id);
        String path = file.getStoragePath();
        String fileType = FileTypeUtil.getTypeByPath(path);
        if (FileUtils.fileIsImageByPath(path)) {
            throw new InternalException("无法预览非图片文件!");
        }
        try (InputStream inputStream = FileUtil.getInputStream(path);
             ServletOutputStream outputStream = response.getOutputStream()) {
            response.setContentType("image/" + fileType);
            response.setContentLengthLong(FileUtil.file(path).length());
            byte[] buffer = new byte[4096];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();
        } catch (IOException e) {
            log.error("预览文件({})时发生错误", path, e);
            throw new InternalException("文件预览失败!");
        }
    }
}
